﻿module SVMTypes

type OpType =
| Register
| Memory
| Constant

type Instruction =
  {
    Symbol        : string
    OpCode        : int64
    Arg1          : Option<OpType list>
    Arg2          : Option<OpType list>
  }

type SVM =
  {
    Registers       : int64 list
    Memory          : int64 list
    InstructionSet  : Instruction list
  }

let init = 00000000L

let instruction_set : Instruction list =
  [
    {Symbol = "NOP";  OpCode = 00000000L; Arg1 = None;  Arg2 = None};
    {Symbol = "LOAD"; OpCode = 00000001L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register]}
    {Symbol = "STORE"; OpCode = 00000010L; Arg1 = Some [Memory;Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "AND"; OpCode = 00000011L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "OR"; OpCode = 00000100L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "NOT"; OpCode = 00000101L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "MOD"; OpCode = 00001000L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "ADD"; OpCode = 00001001L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "SUB"; OpCode = 00001010L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "MUL"; OpCode = 00001011L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "DIV"; OpCode = 00001100L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "EQ"; OpCode = 00001101L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "GRT"; OpCode = 00001110L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "LST"; OpCode = 00001111L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "GEQ"; OpCode = 00010000L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "LEQ"; OpCode = 00010001L; Arg1 = Some [Register]; Arg2 = Some [Memory;Register;Constant]};
    {Symbol = "JMP"; OpCode = 00010010L; Arg1 = Some [Memory]; Arg2 = None};
    {Symbol = "JC"; OpCode = 00010011L; Arg1 = Some [Memory]; Arg2 = Some [Memory;Register]};
    {Symbol = "MOV"; OpCode = 00010100L; Arg1 = Some [Memory;Register]; Arg2 = Some [Memory;Register]};
    {Symbol = "BEGIN"; OpCode = 00011000L; Arg1 = None; Arg2 = None};
    {Symbol = "END"; OpCode = 00011001L; Arg1 = None; Arg2 = None};
  ]

let svm = 
  {
    Registers = [init;init;init;init]
    Memory =
      [for i in [1..100] do
        yield init]
    InstructionSet = instruction_set
  }

let max_val = 11111111L
//funzioni ausiliarie
let list_of_string (s : string) = s.ToCharArray() |> List.ofArray
let string_of_list (l : char list) = List.foldBack (sprintf "%c%s") l ""

